package com.usian.skill.controller;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.usian.skill.common.CodeMsg;
import com.usian.skill.common.Result;
import com.usian.skill.mapper.GoodsMapper;
import com.usian.skill.mq.MQReceiver;
import com.usian.skill.mq.MqSender;
import com.usian.skill.mq.SkillMessage;
import com.usian.skill.pojo.OrderInfo;
import com.usian.skill.pojo.SkillOrder;
import com.usian.skill.service.GoodsService;
import com.usian.skill.service.OrderInfoService;
import com.usian.skill.service.SkillOrderService;
import com.usian.skill.service.SkillService;
import com.usian.skill.vo.GoodsVo;
import com.usian.skill.vo.OrderDetailVo;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.awt.image.BufferedImage;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.List;

@RequestMapping("/skill")
@Controller
public class SkillController implements InitializingBean {
    @Autowired
    private GoodsService goodsService;
    @Autowired
    private SkillOrderService skillOrderService;
    @Autowired
    private SkillService skillService;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private MqSender mqSender;
    //减少Redis的访问
    private HashMap<Long,Boolean> localOverMap = new HashMap<>();

    //完成库存的初始化
    @Override
    public void afterPropertiesSet() throws Exception {
        List<GoodsVo> goodsVoList = goodsService.findAllByDB();
        if (!CollectionUtils.isEmpty(goodsVoList)) {//存在值
            for (GoodsVo vo : goodsVoList) {
                //将商品的信息按照id依次保存
                //取出所有商品的库存，并将库存保存在Redis中
                stringRedisTemplate.opsForValue().set("stockCount" + vo.getId(), vo.getStockCount() + "");
                //商品的库存充足那么久直接设置为FALSE
                localOverMap.put(vo.getId(),false);
            }
        }
    }
    @RequestMapping("/{path}/skillGood")
    @ResponseBody
    public Result skillGoods(HttpSession session, Long goodsId, Model model,@PathVariable String path,Integer verifyCode){
        String userId = (String) session.getAttribute("userId");
        if(userId==null){
            return Result.error(CodeMsg.SESSION_ERROR);
        }
        //验证path是否正确
        boolean checkPath = skillService.checkPath(userId, goodsId, path);
        if(!checkPath){
            return Result.error(CodeMsg.REQUEST_ILLEGAL);
        }
        //检验验证码是否正确
        String code = stringRedisTemplate.opsForValue().get("VerifyCode" + userId + goodsId);
        if(Integer.parseInt(code)!=verifyCode){
            return Result.error(CodeMsg.MIAOSHA_VERIFCODE);
        }
        //查库存
        //GoodsVo goodsVo = goodsService.findById(goodsId);
        //取出Redis中的库存
        //去Redis中进行查询
        //先试用本地map进行判定，如果值为TRUE说明库存已经没了，直接访问秒杀的结果即可，减少对Redis的多次访问
        if(localOverMap.get(goodsId)){
        }
        String stockCount = stringRedisTemplate.opsForValue().get("stockCount" + goodsId);
        //判定库存
        if(Integer.parseInt(stockCount)<=0){//如果库存小于等于0秒杀失败
            localOverMap.put(goodsId,true);
            return Result.error(CodeMsg.MIAO_SHA_OVER);
        }else {
            //预减库存  直接完成数值的减一
            stringRedisTemplate.opsForValue().decrement("stockCount"+goodsId);
            //5-1=4
        }
        //查看之前是否秒杀成功，秒杀成功以后不能再继续秒杀
        SkillOrder skillOrder = skillOrderService.getOne(Wrappers.<SkillOrder>lambdaQuery().eq(SkillOrder::getGoodsId, goodsId).eq(SkillOrder::getUserId, userId));
        if(skillOrder!=null){
            //加上预减库存
            stringRedisTemplate.opsForValue().increment("stockCount"+goodsId);
            return Result.error(CodeMsg.REPEATE_MIAOSHA);
        }
        //减库存,生成订单
        /*OrderInfo info = skillService.skill(userId, goodsVo);
        model.addAttribute("goods",goodsVo);
        model.addAttribute("orderInfo",info);*/
        //入队
        SkillMessage skillMessage = new SkillMessage();
        skillMessage.setGoodsId(goodsId);
        skillMessage.setUserId(userId);
        mqSender.sendSkillMessage(skillMessage);
        //告知用户正在排队
        return Result.success(-1);
    }
    @RequestMapping(value = "/result",method = RequestMethod.GET)
    @ResponseBody
    public Result miaoshaResult(Model model, HttpSession session,
                                @RequestParam("goodsId")Long goodsId){
        String user = (String) session.getAttribute("userId");
        if(user==null){
            return Result.error(CodeMsg.SESSION_ERROR);
        }
        Long result = skillService.getSkillResult(user, goodsId);
        return Result.success(result);
    }
    @RequestMapping(value = "/path",method = RequestMethod.GET)
    @ResponseBody
    public Result getSkillPath(HttpSession session,@RequestParam("goodsId")Long goodsId){
        String user = (String) session.getAttribute("userId");
        if(user==null){
            return Result.error(CodeMsg.SESSION_ERROR);
        }
        //调用创建随机数的方法
        String path = skillService.createMiaoshaPath(user, goodsId);
        return Result.success(path);
    }
    @RequestMapping(value="/verifyCode", method=RequestMethod.GET)
    @ResponseBody
    public Result<String> getMiaoshaVerifyCod(HttpServletResponse response, HttpSession session,
                                              @RequestParam("goodsId")long goodsId) {
        String user=(String)session.getAttribute("userId");
        if(user == null) {
            return Result.error(CodeMsg.SESSION_ERROR);
        }
        try {
            BufferedImage image  = skillService.createVerifyCode(user, goodsId);
            OutputStream out = response.getOutputStream();
            ImageIO.write(image, "JPEG", out);
            out.flush();
            out.close();
            return null;
        }catch(Exception e) {
            e.printStackTrace();
            return Result.error(CodeMsg.MIAOSHA_FAIL);
        }
    }
}
